/*
 * Copyright (c) China Telecom Cloud Technology Co., Ltd. 2024-2025. All rights reserved.
 */
#include "../include/FsStrategy.h"
#include "Common.h"

FsStrategy::FsStrategy(std::string mountPath, 
                    std::string path, 
                    void *addr)
                : fsMountPath(mountPath), 
                shmPath(path), 
                shmAddr(addr) {
    LOG_INFO_FMT("FsStrategy fsMountPath:{}, "
                "shmPath:{}, shmAddr:{}\n",
                fsMountPath.c_str(), 
                shmPath.c_str(), 
                shmAddr
            );
    getSharedMemorySize(shmPath, shmSize);
}




int32_t FsStrategy::getSharedMemorySize(const std::string path,
                                        uint64_t &size) noexcept {
    size = 0;
    int32_t fd = open(path.c_str(), O_RDWR, USER_READ_WRITE);
    if (fd < 0) {
        LOG_ERROR_FMT("Error opening shared memory segment.");
        return KVC_ERR_INTERNAL;
    }
    struct stat fileStat;

    // 根据文件描述符获取文件的元数据
    if (fstat(fd, &fileStat) == -1) {
        LOG_ERROR_FMT("Error statting shared memory segment.");
        close(fd);
        return KVC_ERR_INTERNAL;
    }
    close(fd);
    size = fileStat.st_size;  // 文件大小(字节)
    return KVC_OK;
}



std::string FsStrategy::getFileDirPath(const std::string &objId) {
    auto pos = objId.find(FILE_NAME_SEPARATOR);
    std::string dirName;

    // TODO(yangxianpku: 2025.08.21): 为什么要使用INDEX_MOD，这样会导致很多KV Cache文件重名
    // 上层目录进行打散，文件名保持objid
    if (pos == std::string::npos) {    // 未找到
        // stoll: string to long long
        dirName = std::to_string(std::stoll(objId) % INDEX_MOD);
    } else {
        dirName = std::to_string(std::stoll(objId.substr(0, pos)) % INDEX_MOD);
    }
    return fsMountPath + "/" + LAYOUT + "/" + dirName;
}



// TODO(yangxianpku: 2025.08.21): filePrefix 成员没用上
std::string FsStrategy::getFileFullPath(const std::string &objId) {
    // return getFileDirPath(objId) + "/kvcache_" + objId;
    return getFileDirPath(objId) + "/" 
        + this->filePrefix + objId;
}




int32_t FsStrategy::createFileWithPath(const std::string &path, 
                                    int32_t flags,
                                    mode_t mode) {
    // 取出path的目录部分
    fs::path dir_path = fs::path(path).parent_path();

    // 目录不为空且不存在时创建该目录
    if (!dir_path.empty() && !fs::exists(dir_path)) {
        fs::create_directories(dir_path);
    }

    // 打开文件并返回fd
    return open(path.c_str(), flags, mode);
}